/*
================================================================================
	Plik: main.c
--------------------------------------------------------------------------------
	Autorzy: Piotr Zdunek, Mateusz Słowikowski, Krzysztof Wiąckowski
	Projekt:Model mikrokontrolera AVR
	Kompilator: avr-gcc-4.3.5
	Doc: doxygen 1.7.4
--------------------------------------------------------------------------------
	Zawiera:
--------------------------------------------------------------------------------
	Komentarze:
================================================================================
*/

/*! \mainpage Dokumentacja projektu grupy nr 16
 * \author Mateusz Słowikowski, Krzysztof Wiąckowski, Piotr Zdunek
 * \date 6 czerwca 2011
 *
 * \section task_sec Zadanie Projekt grupy nr. 16
 * \subsection tresc Tresc zadania
 *
 * Dla procesora AVR zaimplementuj i dokładnie przetestuj, podany zestaw instrukcji: \n \n
 *
 * \link F_SWAP SWAP \endlink \n
 * \link F_SEH SEH \endlink \n
 * \link F_ROL ROL \endlink \n
 * \link F_MOVW MOVW \endlink \n
 * \link F_INC INC \endlink \n
 * \link F_CLT CLT \endlink \n
 * \link F_BRVS BRVS \endlink \n
 * \link F_BRHS BRHS \endlink \n
 * \link F_AND AND \endlink \n
 * \link F_SET SET \endlink \n
 * SBIC \n
 * \link F_OR OR \endlink \n
 * LDD \n
 * \link F_CPSE CPSE \endlink \n
 * \link F_CLH CLH \endlink \n
 * \link F_BRPL BRPL \endlink \n
 * \link F_BRCC BRCC \endlink \n \n
 *
 * Proszę pamiętać, iż wiele z podanych instrukcji może pracować w wielu trybach adresowania - należy wszystkie takie warianty uwzględnić w implementacji i testach. \n
 *
 * \section solve_sec Rozwiązanie
 *
 * <b>tutaj będzie warto cos opisać jak to robimy w jakich plikach ile ich będzie itd....</b> \n
 *
 * \section todo_sec Do zrobienia:
 *
 * 1. Dopisać resztę dokumentacji do tego co jest; \n
 * 5. Wywalić tą sekcję przed ostatecznym oddaniem projektu:P;
 *
 */
//!\author Piotr Zdunek
/*!\file
 * \brief Plik główny programu.
 *
 * Main.c - główny plik programu.
 */

#include "includes.h"		//biblioteka zawierające pliki nagłowkowe dołączane do projektu

int main(int argc, char *argv[]) {
	uint16_t T, T2;
	loadMEMC(argv[1]);
	loadMEMD(argv[2]);
	setPC(0x0000);
	InitializeFlagRegister();

#ifndef  DEBUG_MODE
	int i = 0;
	printf("MEMC\n");
	for (i = 0; i < 10; i++)
		printf("0x%04x\n", getMEMC(i));

	printf("MEMD\n");
	for (i = 0; i < 10; i++)
		printf("0x%04x\n", getMEMD(i));
#endif

	uint16_t T_masks[7] = { 0xFFFF, 0xF00F, 0xFC00, 0xF000, 0xF007, 0xF, 0xF008};
	for (;;) {
		T = getMEMC(getPC());
		/*printf("TEST MAIN SWITCH%x, %x\n", T & 0xFF00, (T & 0xFF00) >> 12);
		printf("0x%04x: 0x%04x\n", getPC(), T);
		printf("GLOBAL ERROR = %d\n", GLOBAL_ERROR);*/
#ifndef DEBUG_MODE
		printf("1 T( 0x%04x ) & 0xFFFF = 0x%04x\n",T, T & T_masks[0]);
#endif
		switch ( T & T_masks[0] ) {
			case OPCODE_CLT: { F_CLT(); break; }
			case OPCODE_CLH: { F_CLH(); break; }
			case OPCODE_SEH: { F_SEH(); break; }
			case OPCODE_SET: { F_SET(); break; }
			default: {
#ifndef DEBUG_MODE
				printf("2 T ( 0x%04x ) & 0xF00F = 0x%04x\n",T, T & T_masks[1]);
#endif
				//printf("2 T & 0xF00F = 0x%04x\n", T & T_masks[1]);
				switch (T & T_masks[1] ) {
					case OPCODE_INC:  { F_INC();  break; }
					case OPCODE_LDY2: {
						if		( (T & 0xFF00) == 0x9900 ) 		{ F_SBIC(); }
						else if	( (T & T_masks[1] ) == 0x9009 ) 	{ F_LDY2(); }
						break;
					}
					case OPCODE_LDY3: {
						if		( (T & 0xFF00) == 0x9900 ) 			{ F_SBIC(); }
						else if	( (T & T_masks[1] ) == 0x900a ) 	{ F_LDY3(); }
						break;
					}
					case OPCODE_LDZ2: {
						if	( (T & 0xFF00) == 0x9900 ) 		{ F_SBIC(); }
						else if	( (T & T_masks[1] ) == 0x9001 ) 	{ F_LDZ2(); break; }
						break;
					}
					default:{
#ifndef DEBUG_MODE
						printf("3 T ( 0x%04x ) & 0xFC00 = 0x%04x\n",T, T & T_masks[2]);
#endif
						//printf("3 T & 0xFC00 = 0x%04x\n", T & T_masks[2]);
						switch( T & T_masks[2] ){
							case OPCODE_AND: 	{ F_AND(); 	break; 	}
							case OPCODE_CPSE: 	{ F_CPSE(); break; 	}
							case OPCODE_OR:		{ F_OR(); 	break; 	}
							case OPCODE_ROL:	{ F_ROL(); 	break; 	}
//							case OPCODE_SBIC:	{ F_SBIC(); break; 	}
							case OPCODE_LDZ3: 	{ F_LDZ3(); break; 	}
							case OPCODE_SWAP: 	{ F_SWAP(); break; }
							default:{
#ifndef DEBUG_MODE
								printf("4 T ( 0x%04x ) & 0xF008 = 0x%04x\n",T, T & T_masks[5]);
#endif
								switch ( T & T_masks[3] )  {
								case OPCODE_LDY1_LDDY_LDDZ: {
#ifndef DEBUG_MODE
									printf("4.1 T & 0xF00F = 0x%04x\n",T & T_masks[5]);
#endif
									if( (T & T_masks[1]) == 0x8000 ) 			{ F_LDZ1(); }
									else if ( (T & T_masks[1] ) == 0x8008 )	{ F_LDY1(); }
									else if ( (T & T_masks[5]) <= 7 ) 		{ F_LDDZ(); }
									else if ( (T & T_masks[5]) >=8  )			{ F_LDDY(); }
									break;
								}
								case OPCODE_LDDZ_LDDY: {
									if( (T & T_masks[5]) == 0xa000) { F_LDDY(); }
									else if ( (T & T_masks[5]) <= 7) 	{ F_LDDZ(); }
									else 							{ F_LDDY(); }

									break;
								}
								default: {
#ifndef DEBUG_MODE
									printf("5 T ( 0x%04x ) & 0xF007 = 0x%04x\n",T, T & T_masks[4]);
#endif
									switch( T & T_masks[4] ){
										case OPCODE_BRVS: { F_BRVS(); break; }
										case OPCODE_BRHS: { F_BRHS(); break; }
										case OPCODE_BRPL: { F_BRPL(); break; }
										case OPCODE_BRCC: { F_BRCC(); break; }
										default:{
											if( (T & 0xF100) == 0x0100 ){
													F_MOVW();
													break;
												}else {
												printf(
													"ERROR. WRONG INSTRUCTION. CODE 1\n (PC=0x%04x, T=0x%04x)\r\n",
													getPC(), T);
													saveMEMD( argv[3] );
													return -1;
												}
											}
										}

								}
							}
						}
					}
				}
			}
		}
		}
		saveMEMD(argv[3]);
		}
	return 0;

}
